package org.budo.druid.filter.wall;

import java.sql.DatabaseMetaData;
import java.sql.SQLException;

import org.budo.druid.filter.wrapper.FilterWrapper;

import com.alibaba.druid.filter.FilterChain;
import com.alibaba.druid.proxy.jdbc.ConnectionProxy;
import com.alibaba.druid.proxy.jdbc.DataSourceProxy;
import com.alibaba.druid.proxy.jdbc.PreparedStatementProxy;
import com.alibaba.druid.proxy.jdbc.ResultSetProxy;
import com.alibaba.druid.proxy.jdbc.StatementProxy;
import com.alibaba.druid.util.JdbcUtils;
import com.alibaba.druid.wall.WallFilter;

import lombok.extern.slf4j.Slf4j;

/**
 * @author limingwei
 * @see com.alibaba.druid.wall.WallFilter
 * @see com.alibaba.druid.pool.DruidDataSource#getWallStatValue(boolean)
 */
@Slf4j
public class BudoWallFilter extends WallFilter {
    private String _dbType;

    private boolean _supported = true;

    private FilterWrapper filterWrapper = new FilterWrapper();

    @Override
    public String check(String sql) throws SQLException {
        if (null != sql && sql.trim().toUpperCase().startsWith("DESC ")) {
            log.warn("#35 sql=" + sql + ", this=" + this);
            return sql;
        }

        return super.check(sql);
    }

    @Override
    public synchronized void init(DataSourceProxy dataSource) {
        if (null == dataSource) {
            log.error("#26 dataSource should not be null");
            return;
        }

        if (this._dbType == null || this._dbType.trim().length() == 0) {
            if (dataSource.getDbType() != null) {
                this._dbType = dataSource.getDbType();
            } else {
                this._dbType = JdbcUtils.getDbType(dataSource.getRawJdbcUrl(), "");
            }
        }

        if (this._dbType == null) {
            this._dbType = JdbcUtils.getDbType(dataSource.getUrl(), null);
        }

        if ("sqlite".equals(this._dbType)) {
            this._supported = false; // 不支持的
            return;
        }

        // 支持的
        super.init(dataSource);
    }

    @Override
    public DatabaseMetaData connection_getMetaData(FilterChain chain, ConnectionProxy connection) throws SQLException {
        if (!this._supported) {
            return filterWrapper.connection_getMetaData(chain, connection);
        }

        return super.connection_getMetaData(chain, connection);
    }

    @Override
    public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql) throws SQLException {
        if (!this._supported) {
            return filterWrapper.connection_prepareStatement(chain, connection, sql);
        }

        return super.connection_prepareStatement(chain, connection, sql);
    }

    @Override
    public ResultSetProxy statement_getResultSet(FilterChain chain, StatementProxy statement) throws SQLException {
        if (!this._supported) {
            return filterWrapper.statement_getResultSet(chain, statement);
        }

        return super.statement_getResultSet(chain, statement);
    }

    @Override
    public boolean resultSet_next(FilterChain chain, ResultSetProxy resultSet) throws SQLException {
        if (!this._supported) {
            return filterWrapper.resultSet_next(chain, resultSet);
        }

        return super.resultSet_next(chain, resultSet);
    }
}